package com.weixin.core;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.weixin.config.WxpayConfig;
import com.weixin.interfaces.WeiXinMsg;
import com.weixin.interfaces.WeiXinOrder;
import com.weixin.pojo.message.Message;
import com.weixin.pojo.message.event.ClickReceiveEvent;
import com.weixin.pojo.message.event.LocationReceiveEvent;
import com.weixin.pojo.message.event.ScanReceiveEvent;
import com.weixin.pojo.message.event.SubscribeReceiveEvent;
import com.weixin.pojo.message.event.UnsubscribeReceiveEvent;
import com.weixin.pojo.message.event.ViewReceiveEvent;
import com.weixin.pojo.message.receive.ImageReceiveMessage;
import com.weixin.pojo.message.receive.LinkReceiveMessage;
import com.weixin.pojo.message.receive.LocationReceiveMessage;
import com.weixin.pojo.message.receive.ShortVideoReceiveMessage;
import com.weixin.pojo.message.receive.TextReceiveMessage;
import com.weixin.pojo.message.receive.VideoReceiveMessage;
import com.weixin.pojo.message.receive.VoiceReceiveMessage;
import com.weixin.pojo.pay.response.QueryResponse;
import com.weixin.utils.WxSign;
import com.weixin.utils.WxXml;

/**
 * 类描述：接收微信消息（包含：消息，时间，支付结果通知），并处理<br>
 * <br/>
 * 创建人：邓强 <br>
 * 创建时间：2017年11月6日 下午1:58:00 <br>
 * 修改人： <br>
 * 修改时间：2017年11月6日 下午1:58:00 <br>
 * 修改备注： <br>
 * 
 * @version V1.0
 */
public class WxHandleFactory {
	private static Logger logger = LoggerFactory.getLogger(WxHandleFactory.class);
	private static WeiXinMsg weiXinMsg;
	private static WeiXinOrder weiXinOrder;

	public static void initial(WeiXinMsg weiXinMsg,WeiXinOrder weiXinOrder) {
		WxHandleFactory.weiXinMsg = weiXinMsg;
		WxHandleFactory.weiXinOrder = weiXinOrder;
	}

	public static String Handle(String xml) {
		logger.info("微信消息：{}",xml);
		String renDate = "success";
		Message msg = null;
		if (StringUtils.isNotBlank(xml)) {
			SubscribeReceiveEvent message;
			try {
				message = WxXml.toBean(xml, SubscribeReceiveEvent.class);
				if(message != null && StringUtils.isNotBlank(message.getMsgType())){
					switch (message.getMsgType()) {
					case "text":
						msg = weiXinMsg.handleTextMsg(WxXml.toBean(xml, TextReceiveMessage.class));
						break;
					case "image":
						msg = weiXinMsg.handleImageMsg(WxXml.toBean(xml, ImageReceiveMessage.class));
						break;
					case "voice":
						msg = weiXinMsg.handleVoiceMsg(WxXml.toBean(xml, VoiceReceiveMessage.class));
						break;
					case "video":
						msg = weiXinMsg.handleVideoMsg(WxXml.toBean(xml, VideoReceiveMessage.class));
						break;
					case "shortvideo":
						msg = weiXinMsg.handleShortVideoMsg(WxXml.toBean(xml, ShortVideoReceiveMessage.class));
						break;
					case "location":
						msg = weiXinMsg.handleLocationMsg(WxXml.toBean(xml, LocationReceiveMessage.class));
						break;
					case "link":
						msg = weiXinMsg.handleLinkMsg(WxXml.toBean(xml, LinkReceiveMessage.class));
						break;
					case "event":
						switch (message.getEvent()) {
						case "unsubscribe":
							msg = weiXinMsg.handleUnSubscribeEvent(WxXml.toBean(xml, UnsubscribeReceiveEvent.class));
							break;
						case "subscribe":
							if(StringUtils.isBlank(message.getEventKey())){
								msg = weiXinMsg.handleSubscribeEvent(WxXml.toBean(xml, UnsubscribeReceiveEvent.class));
							}else{
								msg = weiXinMsg.handleSubscribeEvent(WxXml.toBean(xml, SubscribeReceiveEvent.class));
							}
							break;
						case "SCAN":
							msg = weiXinMsg.handleScanEvent(WxXml.toBean(xml, ScanReceiveEvent.class));
							break;
						case "LOCATION":
							msg = weiXinMsg.handleLocationEvent(WxXml.toBean(xml, LocationReceiveEvent.class));
							break;
						case "CLICK":
							msg = weiXinMsg.handleClickEvent(WxXml.toBean(xml, ClickReceiveEvent.class));
							break;
						case "VIEW":
							msg = weiXinMsg.handleViewEvent(WxXml.toBean(xml, ViewReceiveEvent.class));
							break;
						}
						break;
					}
					
					if(msg !=null){
						if(StringUtils.isBlank(msg.getFromUserName())){
							msg.setFromUserName(message.getToUserName());
						}
						if(StringUtils.isBlank(msg.getToUserName())){
							msg.setToUserName(message.getFromUserName());
						}
						renDate = WxXml.toXml(msg);
					}
				}
				
			} catch (Exception e) {
				logger.error("微信推送到服务器的消息转换实体失败 ,xml:" + xml);
			}
		}
		
		
		return renDate;
	}
	
	public static String processOrder(String xml){
		logger.info("微信支付结果通知：{}",xml);
		try {
			//微信支付结果通知
			final QueryResponse notice = WxXml.toBean(xml, QueryResponse.class);
			if (notice != null) {
				ExecutorService threadPoolExecutor = Executors.newCachedThreadPool();
				threadPoolExecutor.execute(new Runnable() {
					@Override
					public void run() {
						try {
							processOrder(notice);
						} catch (Exception e) {
							logger.error("处理微信订单异常", e);
						}
					}
				});
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		
		return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
	}
	
	
	private static void processOrder(QueryResponse notice) {
		// 通信成功
		if ("SUCCESS".equals(notice.getReturn_code())) {
			WxpayConfig wxpayConfig = PayFactory.getWxpayConfig(notice.getAppid());
			String sign;
			try {
				sign = WxSign.getSign(notice,wxpayConfig.getKey());
				// 签名验证成功
				if (sign.equals(notice.getSign())) {
					// 支付成功
					if ("SUCCESS".equals(notice.getResult_code())) {
						weiXinOrder.processSuccessOrder(notice);
					} else {
						logger.error("微信支付失败：{}", WxXml.toXml(notice));
					}
				} else {
					logger.error("微信回调通知被篡改：{}", WxXml.toXml(notice));
				}
			} catch (IllegalAccessException e) {
				logger.error("微信签名算法失败：{}", WxXml.toXml(notice));
			}
			
		} else if ("FAIL".equals(notice.getReturn_code())) {
			weiXinOrder.processFailOrder(notice);
			logger.error("微信扫码支付失败：{}", WxXml.toXml(notice));
		}
	}
}
